const fs = require('fs');//const fs = require('fs')

const parser = require("@babel/parser");//将JS源码转换成语法树的函数
const traverse = require("@babel/traverse").default;//遍历AST的函数
const types = require("@babel/types");//操作节点的函数，比如判断节点类型，生成新的节点等:
const generator = require("@babel/generator").default;//将语法树转换为源代码的函数


function AEOAb() {}

// 初始化 控制流混淆数组 (此函数已人工平坦化)
AEOAb.CsD = function () {
    return {
       VOy: function WiG(XdV, YIZ){
            var aVM = [];
            var bRn = 0;
            while (bRn < XdV) {
                aVM[(bRn + YIZ) % XdV] = [];
                bRn += 1;
            }
            var dES = 0;
            while (dES < XdV) {
                var cmU = XdV - 1;
                while (cmU >= 0) {
                    aVM[dES][(cmU + YIZ * dES) % XdV] = aVM[cmU];
                    cmU -= 1;
                }
                dES += 1;
            }
            return aVM;
        }(16, 8)
    }
}();

// 重新赋值，控制流混淆数组
AEOAb.EFd = function () {
    return typeof AEOAb.CsD.VOy === 'function' ? AEOAb.CsD.VOy.apply(AEOAb.CsD, arguments) : AEOAb.CsD.VOy;
};

// 混淆初始总方法名
var init_func_name = "AEOAb";
// 控制流混淆数组名
var ob_smooth_name = "EFd";

var smooth_func = function (arg1,arg2) {
    let mFunc = init_func_name + "." + ob_smooth_name;
    return eval(mFunc + "()[" + arg1 + "][" + arg2 + "]");
};

const visitor = {
    // 控制流平台化处理
    ForStatement:{
      enter: [replaceForStatement]
    }
};

function replaceForStatement(path){
    // path / container[1]: ForStatement，
    // prevSiblingPath / container[2]:VariableDeclaration
    var prevSiblingPath = path.getPrevSibling();
    if (prevSiblingPath == undefined) {
        return;
    }
    var variableNode = prevSiblingPath.node;
    if (variableNode == undefined
    || variableNode.declarations == undefined
    || variableNode.declarations[0].init == undefined
    || variableNode.declarations[0].init.object == undefined
    || variableNode.declarations[0].init.object.object == undefined) {
        return;
    }
    // 判断变量是否为控制流数组的重新赋值
    if (variableNode.declarations[0]
        .init.object.object.callee.property.name != ob_smooth_name) {
        return;
    }
    var forNode = path.node;
    // 获取SwitchStatement
    var switchBody = forNode.body.body;
    if (!types.isSwitchStatement(switchBody[0])
    || !types.isIdentifier(switchBody[0].discriminant)) { // discriminant:判别式;
        return;
    }

    // 通过相邻上个节点，获取switch的判断变量初始值
    var argInitNode = variableNode.declarations[0].init;
    // 二维数组，f:first,s:second
    let init_arg_f = argInitNode.object.property.value;
    let init_arg_s = argInitNode.property.value;
    var init_arg = smooth_func(init_arg_f, init_arg_s);

    // 获取while循环判定值
    let break_arg_f = forNode.test.right.object.property.value;
    let break_arg_s = forNode.test.right.property.value;
    var break_arg = smooth_func(break_arg_f, break_arg_s);

    var switchStm = switchBody[0];
    var caseList = switchStm.cases;
    var resultBody = [];

    for (;init_arg !== break_arg;) {
        for (let i = 0; i < caseList.length; i++) {
            var case_arg_f = caseList[i].test.object.property.value;
            var case_arg_s = caseList[i].test.property.value;
            var case_arg = smooth_func(case_arg_f, case_arg_s);
            if (init_arg === case_arg) {
                var consequentList = caseList[i].consequent;
                if (types.isBreakStatement(consequentList[consequentList.length -1])
                && types.isExpressionStatement(consequentList[consequentList.length - 2])
                && consequentList[consequentList.length - 2].expression.right.object.object.callee.object.name === init_func_name) {
                    var expressionStat = consequentList[consequentList.length - 2];
                    var state_arg_f = expressionStat.expression.right.object.property.value;
                    var state_arg_s = expressionStat.expression.right.property.value;
                    //更新状态机的值
                    init_arg = smooth_func(state_arg_f, state_arg_s);
                    consequentList.pop(); // 删除break
                    consequentList.pop(); // 删除状态机更换
                } else if (types.isBreakStatement(consequentList[consequentList.length - 1])) {
                    consequentList.pop();
                }
                if (types.isReturnStatement(consequentList[consequentList.length - 1])) {
                    // 以防外层循环出现死循环的情况，遇到"return"时跳出循环
                    init_arg = break_arg;
                }
                resultBody = resultBody.concat(consequentList);
                break;
            }
        }
    }
    path.replaceWithMultiple(resultBody);
	path.getPrevSibling().remove();
}

let test_no = "2";
let rawPath = __dirname + "\\raw_func" + test_no + ".js";
let transPath = __dirname + "\\trans_func" + test_no + ".js";

let jsCode = fs.readFileSync(rawPath, {encoding:"utf-8"});

let ast = parser.parse(jsCode);

traverse(ast, visitor);

let {code} = generator(ast);

fs.writeFile(transPath, code, (err)=>{});

console.log("---- 转换完成 ----");























